package com.example.spring.code.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Set;

public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        try {
            // 创建一个 CachingMetadataReaderFactory 实例，用于读取类的元数据
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            // 通过 ClassPathResource 加载 Config.class 文件，获取其元数据信息
            MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/example/spring/code/a05/Config.class"));
            // 获取所有被 @Bean 注解标记的方法集合
            Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
            // 遍历每个被 @Bean 注解的方法
            methods.stream().forEach(method -> {
                // 获取该方法上的 initMethod 属性值，这里假设只有一个初始化方法名
                String initMethod = method.getAllAnnotationAttributes(Bean.class.getName()).get("initMethod").get(0).toString();

                // 创建一个 BeanDefinitionBuilder 实例，用于构建 Bean 定义
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                // 设置工厂方法和工厂方法所属的 Bean 名称（即 config）
                builder.setFactoryMethodOnBean(method.getMethodName(), "config");
                // 设置自动装配模式为构造器注入
                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                // 如果 initMethod 不为空，则设置 Bean 的初始化方法
                if (initMethod.length() > 0) {
                    builder.setInitMethodName(initMethod);
                }
                // 构建最终的 AbstractBeanDefinition 对象
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                // 将构建好的 BeanDefinition 注册到容器中，Bean 名称为方法名
                registry.registerBeanDefinition(method.getMethodName(), beanDefinition);
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
